﻿
Imports std
Imports tcpServer2

Public MustInherit Class rrserver
    Public Shared ReadOnly defaultThreadCount As Int64 = tcpServer2.defaultThreadCount
    Private WithEvents server As tcpServer2 = Nothing
    Protected MustOverride Function run(ByRef id As String, ByVal cmd As vector(Of String), _
                                        ByVal distrRuleId As String, ByVal distrRule As String, _
                                        ByRef errorInfo As String) As Boolean
    Protected MustOverride Function status(ByVal id As String, ByRef percentage As Int64, _
                                           ByRef errorInfo As String) As Boolean
    Protected MustOverride Function return_jobid() As Boolean

    Protected Delegate Function matchActionDelegate(ByVal p As pair(Of String, String)) As Boolean
    Protected Delegate Sub handleActionDelegate(ByVal handle As talkHandle, _
                                                ByVal p As vector(Of pair(Of String, String)))
    Private matchActions As vector(Of matchActionDelegate) = Nothing
    Private handleActions As vector(Of handleActionDelegate) = Nothing

    Protected Sub insertMatchAction(ByVal m As matchActionDelegate)
        matchActions.push_back(m)
    End Sub

    Protected Sub insertHandleAction(ByVal h As handleActionDelegate)
        handleActions.push_back(h)
    End Sub

    Protected Sub New(ByVal port As Int32)
        server = New tcpServer2()
        server.port = port
        matchActions = New vector(Of matchActionDelegate)()
        handleActions = New vector(Of handleActionDelegate)()
        insertMatchAction(AddressOf matchRun)
        insertHandleAction(AddressOf run)
        insertMatchAction(AddressOf matchStatus)
        insertHandleAction(AddressOf status)
    End Sub

    Public Function health() As Boolean
        Return server.health()
    End Function

    Public Sub start()
        server.start()
    End Sub

    Public Sub [stop]()
        server.stop()
    End Sub

    Protected Shared Sub return_failed(ByVal handle As talkHandle, ByVal errorInfo As String)
        nettransDataInserter.keyvaluepair(handle, _
                                          protocols.result, protocols.results.failed, _
                                          protocols.errorInfo, errorInfo)
    End Sub

    Protected Shared Sub return_success(ByVal handle As talkHandle)
        nettransDataInserter.keyvaluepair(handle, protocols.result, protocols.results.success)
    End Sub

    Private Sub status(ByVal handle As talkHandle, ByVal id As String)
        Dim p As Int64 = 0
        Dim errorInfo As String = Nothing
        If status(id, p, errorInfo) Then
            nettransDataInserter.keyvaluepair(handle, _
                                              protocols.result, protocols.results.success, _
                                              protocols.percentage, Convert.ToString(p))
        Else
            raiseError(errorInfo, errorHandle.errorType.warning)
            return_failed(handle, errorInfo)
        End If
    End Sub

    Private Sub status(ByVal handle As talkHandle, ByVal p As vector(Of pair(Of String, String)))
        assert(Not handle Is Nothing)
        assert(Not p Is Nothing)
        Dim i As Int64
        For i = 0 To p.size() - 1
            If matchProtocol(p(i), protocols.jobid) Then
                status(handle, action(p(i)))
                Exit For
            End If
        Next
        If i = p.size() Then
            Dim msg As String = Nothing
            msg = "no " + protocols.jobid + " found in request dataset."
            raiseError(msg, errorHandle.errorType.warning)
            return_failed(handle, msg)
        End If
    End Sub

    Private Sub run(ByVal handle As talkHandle, _
                    ByRef jobid As String, ByVal cmd As vector(Of String), _
                    ByVal distrRuleId As String, ByVal distrRule As String)
        Dim errorInfo As String = Nothing
        If run(jobid, cmd, distrRuleId, distrRule, errorInfo) Then
            If return_jobid() Then
                nettransDataInserter.keyvaluepair(handle, _
                                                  protocols.result, protocols.results.success, _
                                                  protocols.jobid, jobid)
            Else
                return_success(handle)
            End If
        Else
            raiseError(errorInfo, errorHandle.errorType.warning)
            return_failed(handle, errorInfo)
        End If
    End Sub

    Private Sub run(ByVal handle As talkHandle, ByVal p As vector(Of pair(Of String, String)))
        assert(Not handle Is Nothing)
        assert(Not p Is Nothing)
        Dim cmd As vector(Of String) = Nothing
        Dim distrRule As String = Nothing
        Dim distrRuleId As String = Nothing
        Dim jobid As String = Nothing
        cmd = New vector(Of String)()
        For i As Int64 = 0 To p.size() - 1
            If matchProtocol(p(i), protocols.command) Then
                cmd.push_back(action(p(i)))
            ElseIf matchProtocol(p(i), protocols.distrrule) Then
                copy(distrRule, action(p(i)))
            ElseIf matchProtocol(p(i), protocols.distrruleId) Then
                copy(distrRuleId, action(p(i)))
            ElseIf matchProtocol(p(i), protocols.jobid) Then
                copy(jobid, action(p(i)))
            End If
        Next

        If cmd.size() = 0 Then
            Dim msg As String = Nothing
            msg = "no " + protocols.command + " found in request dataset."
            raiseError(msg, errorHandle.errorType.warning)
            return_failed(handle, msg)
        Else
            run(handle, jobid, cmd, distrRuleId, distrRule)
        End If
    End Sub

    Private Shared Function matchRun(ByVal p As pair(Of String, String))
        Return matchAction(p, protocols.actions.run)
    End Function

    Private Shared Function matchStatus(ByVal p As pair(Of String, String))
        Return matchAction(p, protocols.actions.status)
    End Function

    Private Sub server_receive(ByVal handle As talkHandle) Handles server.receive
        assert(Not handle Is Nothing)
        assert(matchActions.size() = handleActions.size())
        Dim p As vector(Of pair(Of String, String)) = Nothing
        If nettransDataParser.keyvaluepair(handle.receiveData, p) AndAlso Not p Is Nothing AndAlso p.size() > 0 Then
            Dim i As Int64
            For i = 0 To p.size() - 1
                If matchProtocol(p(i), protocols.action) Then
                    Dim j As Int64
                    For j = 0 To matchActions.size() - 1
                        If matchActions(j)(p(i)) Then
                            handleActions(j)(handle, p)
                            Exit For
                        End If
                    Next
                    If j = matchActions.size() Then
                        Dim msg As String = Nothing
                        msg = "action do not match any handler."
                        raiseError(msg, errorHandle.errorType.warning)
                        return_failed(handle, msg)
                    End If
                    Exit For
                End If
            Next
            If i = p.size() Then
                Dim msg As String = Nothing
                msg = "no " + protocols.action + " found in request dataset."
                raiseError(msg, errorHandle.errorType.warning)
                return_failed(handle, msg)
            End If
        Else
            Dim msg As String = Nothing
            msg = "cannot parse keyvalue pair from request dataset."
            raiseError(msg, errorHandle.errorType.warning)
            return_failed(handle, msg)
        End If
    End Sub
End Class
